package service

import (
	"errors"
	"lsgfish/server/internal/config"
	"lsgfish/server/internal/model"
	"lsgfish/server/internal/repo"
	"lsgfish/server/internal/tool"
	"time"

	"gorm.io/gorm"
)

// LoginService 用户服务接口
type LoginService interface {
	//注册
	Register(req *model.User) (string, error)
	// 登录
	Login(req *model.User) (string, error)
	// 发送注册验证码
	SendRegisterVerifyCode(email string) error
	// 发送登录验证码
	SendLoginVerifyCode(req model.User) error
	// 检查账号是否重复注册
	CheckEmailRepeat(account string) error
	// 验证码登录
	VerifyCodeLogin(req model.User) (string, error)
}

type loginService struct {
	userRepo repo.UserRepository
}

// 创建用户服务
func NewLoginService() LoginService {
	return &loginService{
		userRepo: repo.NewUserRepository(),
	}
}

// 生成邀请码
func (s *loginService) GenerateInviteCode(user *model.User) error {
	if code, err := tool.GenerateInviteCode(); err != nil {
		return err
	} else {
		user.InviteCode = code
		if err := s.userRepo.Updates(*user); err != nil {
			return err
		}
	}
	return nil
}

// 修改密码
func (s *loginService) ChangePassword(user model.User) error {

	return s.userRepo.Updates(user)
}

// 检查账号是否重复注册
func (s *loginService) CheckEmailRepeat(email string) error {
	if user, err := s.userRepo.Query(email); err != nil && err != gorm.ErrRecordNotFound {
		return err
	} else if user.Account != "" {
		return errors.New("账号已注册")
	}
	return nil
}

// 实现用户注册
func (s *loginService) Register(req *model.User) (string, error) {
	if err := s.userRepo.Register(req); err != nil {
		return "", err
	}
	return generatorToken(s.userRepo, *req)
}

// 验证码登录
func (s *loginService) VerifyCodeLogin(req model.User) (string, error) {

	user, err := s.userRepo.Query(req.Account)
	if err != nil {
		return "", err
	}

	// 生成token
	token, err := tool.GenerateToken(user)
	if err != nil {
		return "", errors.New("生成token失败")
	}

	// 保存token到Redis
	if err := tool.RedisServiceTool.SetToken(token, user); err != nil {
		return "", errors.New("保存token失败")
	}

	// 删除登录验证码

	return token, nil
}

// 实现用户登录
func (s *loginService) Login(req *model.User) (string, error) {
	user, err := s.userRepo.Query(req.Account)
	if err != nil {
		return "", err
	}

	// 验证密码
	if !tool.ComparePasswords(user.Password, req.Password) {
		return "", errors.New("账号或密码错误")
	}
	// 查询token是否存在，如果存在则删除旧token缓存
	if user.Token != "" {
		tool.RedisServiceTool.DeleteToken(user.Token)
	}
	token, err := generatorToken(s.userRepo, user)
	return token, err
}

// 发送注册验证码
func (s *loginService) SendRegisterVerifyCode(email string) error {
	var (
		code string
		err  error
	)

	// 检查验证码是否存在
	if code, err = tool.RedisServiceTool.GetCode(email, tool.RegisterVerifyCodePrefix); err != nil {
		return err
	} else if code != "" {
		return errors.New("验证码未过期，请勿频繁请求验证码")
	}

	// 检查账号是否已经存在
	if err := s.CheckEmailRepeat(email); err != nil {
		return err
	}

	// 生成验证码
	if code, err = tool.GenerateVerificationCode(6); err != nil {
		return err
	}

	// 发送验证码
	if err := tool.SendEmailVerification(email, code, "登录注册"); err != nil {
		return err
	}

	// 保存验证码到Redis
	if err = tool.RedisServiceTool.SetCode(email, code, tool.RegisterVerifyCodePrefix, time.Minute*time.Duration(config.Conf.Email.Expire)); err != nil {
		return err
	}

	return nil
}

// 发送登录验证码
func (s *loginService) SendLoginVerifyCode(req model.User) error {
	// 检查账号是否存在
	if _, err := s.userRepo.Query(req.Account); err != nil && err != gorm.ErrRecordNotFound {
		return err
	}

	// 查看缓存是否已经存在验证码
	if code, err := tool.RedisServiceTool.GetCode(req.Account, tool.LoginVerifyCodePrefix); err != nil {
		return err
	} else if code != "" {
		return errors.New("验证码已发送，请勿重复发送")
	}

	// 生成登录验证码
	if code, err := tool.GenerateVerificationCode(6); err == nil {
		req.VerifyCode = code
	} else {
		return err
	}

	// 发送验证码
	if err := tool.SendEmailVerification(req.Account, req.VerifyCode, "验证码登录"); err != nil {
		return err
	}

	// 保存验证码到Redis
	if err := tool.RedisServiceTool.SetCode(req.Account, req.VerifyCode, tool.LoginVerifyCodePrefix, time.Minute*time.Duration(config.Conf.Email.Expire)); err != nil {
		return err
	}

	return nil
}
